home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume23 / zip / part07 < prev    next >
Encoding:
Text File  |  1991-10-20  |  53.9 KB  |  1,810 lines

  1. Newsgroups: comp.sources.misc
  2. From: kirsch@usasoc.soc.mil (David Kirschbaum)
  3. Subject:  v23i094:  zip - Portable zip v1.0, Part07/09
  4. Message-ID: <1991Oct21.042217.8186@sparky.imd.sterling.com>
  5. X-Md4-Signature: 6773101a8911f04410c9cf3dd6939e08
  6. Date: Mon, 21 Oct 1991 04:22:17 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: kirsch@usasoc.soc.mil (David Kirschbaum)
  10. Posting-number: Volume 23, Issue 94
  11. Archive-name: zip/part07
  12. Environment: UNIX, Minix, MSDOS, OS/2, VMS
  13.  
  14. #! /bin/sh
  15. # into a shell via "sh file" or similar.  To overwrite existing files,
  16. # type "sh file -c".
  17. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  18. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  19. # Contents:  ziperr.h zipfile.c zipsplit.c zipup.c
  20. # Wrapped by kent@sparky on Sun Oct 20 22:58:55 1991
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. echo If this archive is complete, you will see the following message:
  23. echo '          "shar: End of archive 7 (of 9)."'
  24. if test -f 'ziperr.h' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'ziperr.h'\"
  26. else
  27.   echo shar: Extracting \"'ziperr.h'\" \(2561 characters\)
  28.   sed "s/^X//" >'ziperr.h' <<'END_OF_FILE'
  29. X/*
  30. X
  31. X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
  32. X Permission is granted to any individual or institution to use, copy, or
  33. X redistribute this software so long as all of the original files are included
  34. X unmodified, that it is not sold for profit, and that this copyright notice
  35. X is retained.
  36. X
  37. X*/
  38. X
  39. X/*
  40. X *  ziperr.h by Mark Adler.
  41. X */
  42. X
  43. X/* Error return values.  The values 0..4 and 12..18 follow the conventions
  44. X   of PKZIP.   The values 4..10 are all assigned to "insufficient memory"
  45. X   by PKZIP, so the codes 5..10 are used here for other purposes. */
  46. X#define ZE_MISS         -1      /* used by procname(), zipbare() */
  47. X#define ZE_OK           0       /* success */
  48. X#define ZE_EOF          2       /* unexpected end of zip file */
  49. X#define ZE_FORM         3       /* zip file structure error */
  50. X#define ZE_MEM          4       /* out of memory */
  51. X#define ZE_LOGIC        5       /* internal logic error (implode) */
  52. X#define ZE_BIG          6       /* entry too large to split */
  53. X#define ZE_NOTE         7       /* invalid comment format */
  54. X#define ZE_ABORT        9       /* user interrupt or termination */
  55. X#define ZE_TEMP         10      /* error using a temp file */
  56. X#define ZE_READ         11      /* read or seek error */
  57. X#define ZE_NONE         12      /* nothing to do */
  58. X#define ZE_NAME         13      /* missing or empty zip file */
  59. X#define ZE_WRITE        14      /* error writing to a file */
  60. X#define ZE_CREAT        15      /* couldn't open to write */
  61. X#define ZE_PARMS        16      /* bad command line */
  62. X#define ZE_OPEN         18      /* could not open a specified file to read */
  63. X/* Macro to determine whether to call perror() or not */
  64. X#define PERR(e) (e==ZE_READ||e==ZE_WRITE||e==ZE_CREAT||e==ZE_TEMP||e==ZE_OPEN)
  65. X
  66. X#ifdef GLOBALS
  67. X/* Error messages for the err() function in the zip programs */
  68. Xchar *errors[] = {
  69. X/*  1 */  "",
  70. X/*  2 */  "Unexpected end of zip file",
  71. X/*  3 */  "Zip file structure invalid",
  72. X/*  4 */  "Out of memory",
  73. X/*  5 */  "Internal logic error",
  74. X/*  6 */  "Entry too big to split",
  75. X/*  7 */  "Invalid comment format",
  76. X/*  8 */  "",
  77. X/*  9 */  "Interrupted",
  78. X/* 10 */  "Temporary file failure",
  79. X/* 11 */  "Input file read failure",
  80. X/* 12 */  "Nothing to do!",
  81. X/* 13 */  "Missing or empty zip file",
  82. X/* 14 */  "Output file write failure",
  83. X/* 15 */  "Could not create output file",
  84. X/* 16 */  "Invalid command arguments",
  85. X/* 17 */  "",
  86. X/* 18 */  "File not found or no read permission",
  87. X};
  88. X#else /* !GLOBALS */
  89. Xextern char *errors[];          /* Error messages for err() */
  90. X#endif /* ?GLOBALS */
  91. END_OF_FILE
  92.   if test 2561 -ne `wc -c <'ziperr.h'`; then
  93.     echo shar: \"'ziperr.h'\" unpacked with wrong size!
  94.   fi
  95.   # end of 'ziperr.h'
  96. fi
  97. if test -f 'zipfile.c' -a "${1}" != "-c" ; then 
  98.   echo shar: Will not clobber existing file \"'zipfile.c'\"
  99. else
  100.   echo shar: Extracting \"'zipfile.c'\" \(20530 characters\)
  101.   sed "s/^X//" >'zipfile.c' <<'END_OF_FILE'
  102. X/*
  103. X
  104. X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
  105. X Permission is granted to any individual or institution to use, copy, or
  106. X redistribute this software so long as all of the original files are included
  107. X unmodified, that it is not sold for profit, and that this copyright notice
  108. X is retained.
  109. X
  110. X*/
  111. X
  112. X/*
  113. X *  zipfile.c by Mark Adler.
  114. X */
  115. X
  116. X#include "zip.h"
  117. X
  118. X
  119. X/* Macros for converting integers in little-endian to machine format */
  120. X#define SH(a) (((ush)(uch)(a)[0]) | (((ush)(uch)(a)[1]) << 8))
  121. X#define LG(a) ((ulg)SH(a) | ((ulg)SH((a)+2) << 16))
  122. X
  123. X/* Macros for writing machine integers to little-endian format */
  124. X#define PUTSH(a,f) {putc((char)(a),(f)); putc((char)((a) >> 8),(f));}
  125. X#define PUTLG(a,f) {PUTSH(a,f) PUTSH((a) >> 16,f)}
  126. X
  127. X
  128. X/* -- Structure of a ZIP file -- */
  129. X
  130. X/* Signatures for zip file information headers */
  131. X#define LOCSIG  0x04034b50L
  132. X#define CENSIG  0x02014b50L
  133. X#define ENDSIG  0x06054b50L
  134. X
  135. X/* Offsets of values in headers */
  136. X#define LOCVER  0               /* version needed to extract */
  137. X#define LOCFLG  2               /* encrypt, implosion flags */
  138. X#define LOCHOW  4               /* compression method */
  139. X#define LOCTIM  6               /* last modified file time, DOS format */
  140. X#define LOCDAT  8               /* last modified file date, DOS format */
  141. X#define LOCCRC  10              /* uncompressed crc-32 for file */
  142. X#define LOCSIZ  14              /* compressed size in zip file */
  143. X#define LOCLEN  18              /* uncompressed size */
  144. X#define LOCNAM  22              /* length of filename */
  145. X#define LOCEXT  24              /* length of extra field */
  146. X
  147. X#define CENVEM  0               /* version made by */
  148. X#define CENVER  2               /* version needed to extract */
  149. X#define CENFLG  4               /* encrypt, implosion flags */
  150. X#define CENHOW  6               /* compression method */
  151. X#define CENTIM  8               /* last modified file time, DOS format */
  152. X#define CENDAT  10              /* last modified file date, DOS format */
  153. X#define CENCRC  12              /* uncompressed crc-32 for file */
  154. X#define CENSIZ  16              /* compressed size in zip file */
  155. X#define CENLEN  20              /* uncompressed size */
  156. X#define CENNAM  24              /* length of filename */
  157. X#define CENEXT  26              /* length of extra field */
  158. X#define CENCOM  28              /* file comment length */
  159. X#define CENDSK  30              /* disk number start */
  160. X#define CENATT  32              /* internal file attributes */
  161. X#define CENATX  34              /* external file attributes */
  162. X#define CENOFF  38              /* relative offset of local header */
  163. X
  164. X#define ENDDSK  0               /* number of this disk */
  165. X#define ENDBEG  2               /* number of the starting disk */
  166. X#define ENDSUB  4               /* entries on this disk */
  167. X#define ENDTOT  6               /* total number of entries */
  168. X#define ENDSIZ  8               /* size of entire central directory */
  169. X#define ENDOFF  12              /* offset of central on starting disk */
  170. X#define ENDCOM  16              /* length of zip file comment */
  171. X
  172. X
  173. X/* Local functions */
  174. X#ifdef PROTO
  175. X   local int zqcmp(voidp *, voidp *);
  176. X#  ifndef UTIL
  177. X     local int zbcmp(voidp *, voidp far *);
  178. X     local char *cutpath(char *);
  179. X#  endif /* !UTIL */
  180. X#endif /* PROTO */
  181. X
  182. X
  183. Xlocal int zqcmp(a, b)
  184. Xvoidp *a, *b;           /* pointers to pointers to zip entries */
  185. X/* Used by qsort() to compare entries in the zfile list.  */
  186. X{
  187. X  return strcmp((*(struct zlist far **)a)->zname,
  188. X                (*(struct zlist far **)b)->zname);
  189. X}
  190. X
  191. X
  192. X#ifndef UTIL
  193. X
  194. Xlocal int zbcmp(n, z)
  195. Xvoidp *n;               /* string to search for */
  196. Xvoidp far *z;           /* pointer to a pointer to a zip entry */
  197. X/* Used by search() to compare a target to an entry in the zfile list. */
  198. X{
  199. X#ifdef OS2
  200. X  return stricmp((char *)n, ((struct zlist far *)z)->zname);
  201. X#else /* !OS2 */
  202. X  return strcmp((char *)n, ((struct zlist far *)z)->zname);
  203. X#endif /* ?OS2 */
  204. X}
  205. X
  206. X
  207. Xstruct zlist far *zsearch(n)
  208. Xchar *n;                /* name to find */
  209. X/* Return a pointer to the entry in zfile with the name n, or NULL if
  210. X   not found. */
  211. X{
  212. X  voidp far **p;        /* result of search() */
  213. X
  214. X  if (zcount && (p = search(n, (voidp far **)zsort, zcount, zbcmp)) != NULL)
  215. X    return *(struct zlist far **)p;
  216. X  else
  217. X    return NULL;
  218. X}
  219. X
  220. X#endif /* !UTIL */
  221. X
  222. X
  223. X#ifdef VMS
  224. X#  define PATHCUT ']'
  225. X#else /* !VMS */
  226. X#  define PATHCUT '/'
  227. X#endif /* VMS */
  228. X
  229. Xchar *ziptyp(s)
  230. Xchar *s;                /* file name to force to zip */
  231. X/* If the file name *s has a dot (other than the first char), then return
  232. X   the name, otherwise append .zip to the name.  Allocate the space for
  233. X   the name in either case.  Return a pointer to the new name, or NULL
  234. X   if malloc() fails. */
  235. X{
  236. X  char *q;              /* temporary pointer */
  237. X  char *t;              /* pointer to malloc'ed string */
  238. X
  239. X  if ((t = malloc(strlen(s) + 5)) == NULL)
  240. X    return NULL;
  241. X  strcpy(t, s);
  242. X#ifdef MSDOS
  243. X  for (q = t; *q; q++)
  244. X    if (*q == '\\')
  245. X      *q = '/';
  246. X#endif /* MSDOS */
  247. X  if (strrchr((q = strrchr(t, PATHCUT)) == NULL ? t : q + 1, '.') == NULL)
  248. X    strcat(t, ".zip");
  249. X#ifdef MSDOS
  250. X#ifndef OS2
  251. X  strupr(t);
  252. X#endif /* !OS2 */
  253. X#endif /* MSDOS */
  254. X  return t;
  255. X}
  256. X
  257. X
  258. Xint readzipfile()
  259. X/*
  260. X   Make first pass through zip file, reading information from local file
  261. X   headers and then verifying that information with the central file
  262. X   headers.  Any deviation from the expected zip file format returns an
  263. X   error.  At the end, a sorted list of file names in the zip file is made
  264. X   to facilitate searching by name.
  265. X
  266. X   The name of the zip file is pointed to by the global "zipfile".  The
  267. X   globals zfiles, zcount, zcomlen, zcomment, and zsort are filled in.
  268. X   Return an error code in the ZE_ class.
  269. X*/
  270. X{
  271. X  char b[CENHEAD];      /* buffer for central headers */
  272. X  FILE *f;              /* zip file */
  273. X  int m;                /* mismatch flag */
  274. X  extent n;             /* length of name */
  275. X  ulg p;                /* current file offset */
  276. X  char r;               /* holds reserved bits during memcmp() */
  277. X  ulg s;                /* size of data, start of central */
  278. X  char *t;              /* temporary variable */
  279. X  char far *u;          /* temporary variable */
  280. X  struct zlist far * far *x;    /* pointer last entry's link */
  281. X  struct zlist far *z;  /* current zip entry structure */
  282. X
  283. X  /* Initialize zip file info */
  284. X  zipbeg = 0;
  285. X  zfiles = NULL;                        /* Points to first header */
  286. X  zcomlen = 0;                          /* zip file comment length */
  287. X
  288. X  /* If zip file exists, read headers and check structure */
  289. X  if ((f = fopen(zipfile, FOPR)) != NULL)
  290. X  {
  291. X    x = &zfiles;                        /* first link */
  292. X    p = 0;                              /* starting file offset */
  293. X    zcount = 0;                         /* number of files */
  294. X
  295. X    /* Find start of zip structures */
  296. X    while (fread(b, 4, 1, f) == 1 && (s = LG(b)) != LOCSIG && s != ENDSIG)
  297. X      if (fseek(f, -3L, SEEK_CUR))
  298. X        return ferror(f) ? ZE_READ : ZE_EOF;
  299. X      else
  300. X        p++;
  301. X    zipbeg = p;
  302. X
  303. X    /* Read local headers */
  304. X    while (LG(b) == LOCSIG)
  305. X    {
  306. X      /* Read local header raw to compare later with central header 
  307. X         (this requires that the offest of ext in the zlist structure
  308. X         be greater than or equal to LOCHEAD) */
  309. X      if ((z = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL)
  310. X        return ZE_MEM;
  311. X      if (fread(b, LOCHEAD, 1, f) != 1)
  312. X        return ferror(f) ? ZE_READ : ZE_EOF;
  313. X      t = b;  u = (char far *)z;  n = LOCHEAD;
  314. X      do {
  315. X        *u++ = *t++;
  316. X      } while (--n);
  317. X
  318. X      /* Link into list */
  319. X      *x = z;
  320. X      z->nxt = NULL;
  321. X      x = &z->nxt;
  322. X
  323. X      /* Read file name and extra field and skip data */
  324. X      n = SH(LOCNAM + (uch far *)z);
  325. X      z->ext = SH(LOCEXT + (uch far *)z);
  326. X      s = LG(LOCSIZ + (uch far *)z);
  327. X      if (n == 0)
  328. X      {
  329. X        sprintf(errbuf, "%d", zcount + 1);
  330. X        warn("zero-length name for entry #", errbuf);
  331. X        return ZE_FORM;
  332. X      }
  333. X      if ((z->zname = malloc(n+1)) ==  NULL ||
  334. X          (z->ext && (z->extra = malloc(z->ext)) == NULL))
  335. X        return ZE_MEM;
  336. X      if (fread(z->zname, n, 1, f) != 1 ||
  337. X          (z->ext && fread(z->extra, z->ext, 1, f) != 1) ||
  338. X          fseek(f, (long)s, SEEK_CUR))
  339. X        return ferror(f) ? ZE_READ : ZE_EOF;
  340. X      z->zname[n] = 0;                  /* terminate name */
  341. X#ifdef UTIL
  342. X      z->name = z->zname;
  343. X#else /* !UTIL */
  344. X      z->name = in2ex(z->zname);        /* convert to external name */
  345. X      if (z->name == NULL)
  346. X        return ZE_MEM;
  347. X#endif /* ?UTIL */
  348. X
  349. X      /* Save offset, update for next header */
  350. X      z->off = p;
  351. X      p += 4 + LOCHEAD + n + z->ext + s;
  352. X      zcount++;
  353. X
  354. X      /* Read next signature */
  355. X      if (fread(b, 4, 1, f) != 1)
  356. X        return ferror(f) ? ZE_READ : ZE_EOF;
  357. X    }
  358. X
  359. X    /* Point to start of header list and read central headers */
  360. X    z = zfiles;
  361. X    s = p;                              /* save start of central */
  362. X    while (LG(b) == CENSIG)
  363. X    {
  364. X      if (z == NULL)
  365. X      {
  366. X        warn("extraneous central header signature", "");
  367. X        return ZE_FORM;
  368. X      }
  369. X
  370. X      /* Read central header */
  371. X      if (fread(b, CENHEAD, 1, f) != 1)
  372. X        return ferror(f) ? ZE_READ : ZE_EOF;
  373. X
  374. X      /* Compare local header with that part of central header (except
  375. X         for the reserved bits in the general purpose flags and except
  376. X         for length of extra fields--authentication can make these
  377. X         different in central and local headers) */
  378. X      z->lflg = SH(LOCFLG + (uch far *)z);      /* Save reserved bits */
  379. X      r = b[CENFLG+1];
  380. X      ((uch far *)z)[LOCFLG+1] &= 0x1f; /* Zero out reserved bits */
  381. X      b[CENFLG+1] &= 0x1f;
  382. X      for (m = 0, u = (char far *)z, n = 0; n < LOCHEAD - 2; n++)
  383. X        if (u[n] != b[n+2])
  384. X        {
  385. X          if (!m)
  386. X            warn("local and central headers differ for ", z->zname);
  387. X          m = 1;
  388. X          sprintf(errbuf, " offset %d--local = %02x, central = %02x",
  389. X                  n, (uch)u[n], (uch)b[n+2]);
  390. X          warn(errbuf, "");
  391. X        }
  392. X      if (m)
  393. X        return ZE_FORM;
  394. X      b[CENFLG+1] = r;                  /* Restore reserved bits */
  395. X
  396. X      /* Overwrite local header with translated central header */
  397. X      z->vem = SH(CENVEM + b);
  398. X      z->ver = SH(CENVER + b);
  399. X      z->flg = SH(CENFLG + b);          /* may be different from z->lflg */
  400. X      z->how = SH(CENHOW + b);
  401. X      z->tim = LG(CENTIM + b);          /* time and date into one long */
  402. X      z->crc = LG(CENCRC + b);
  403. X      z->siz = LG(CENSIZ + b);
  404. X      z->len = LG(CENLEN + b);
  405. X      z->nam = SH(CENNAM + b);
  406. X      z->cext = SH(CENEXT + b);         /* may be different from z->ext */
  407. X      z->com = SH(CENCOM + b);
  408. X      z->dsk = SH(CENDSK + b);
  409. X      z->att = SH(CENATT + b);
  410. X      z->atx = LG(CENATX + b);
  411. X      if (z->off != LG(CENOFF + b))
  412. X      {
  413. X        warn("local offset in central header incorrect for ", z->zname);
  414. X        return ZE_FORM;
  415. X      }
  416. X
  417. X      /* Compare name and extra fields and read comment field */
  418. X      if ((t = malloc(z->nam)) == NULL)
  419. X        return ZE_MEM;
  420. X      if (fread(t, z->nam, 1, f) != 1)
  421. X      {
  422. X        free((voidp *)t);
  423. X        return ferror(f) ? ZE_READ : ZE_EOF;
  424. X      }
  425. X      if (memcmp(t, z->zname, z->nam))
  426. X      {
  427. X        free((voidp *)t);
  428. X        warn("names in local and central differ for ", z->zname);
  429. X        return ZE_FORM;
  430. X      }
  431. X      free((voidp *)t);
  432. X      if (z->cext)
  433. X      {
  434. X        if ((z->cextra = malloc(z->cext)) == NULL)
  435. X          return ZE_MEM;
  436. X        if (fread(z->cextra, z->cext, 1, f) != 1)
  437. X        {
  438. X          free((voidp *)(z->cextra));
  439. X          return ferror(f) ? ZE_READ : ZE_EOF;
  440. X        }
  441. X        if (z->ext == z->cext && memcmp(z->extra, z->cextra, z->ext) == 0)
  442. X        {
  443. X          free((voidp *)(z->cextra));
  444. X          z->cextra = z->extra;
  445. X        }
  446. X      }
  447. X      if (z->com)
  448. X      {
  449. X        if ((z->comment = malloc(z->com)) == NULL)
  450. X          return ZE_MEM;
  451. X        if (fread(z->comment, z->com, 1, f) != 1)
  452. X        {
  453. X          free((voidp *)(z->comment));
  454. X          return ferror(f) ? ZE_READ : ZE_EOF;
  455. X        }
  456. X      }
  457. X
  458. X      /* Note oddities */
  459. X      if (verbose)
  460. X      {
  461. X        if (z->vem != 10 && z->vem != 11 &&
  462. X            (n = z->vem >> 8) != 3 && n != 2 && n != 6)
  463. X        {
  464. X          sprintf(errbuf, "made by version %d.%d on system type %d: ",
  465. X                  (z->vem & 0xff) / 10, (z->vem & 0xff) % 10, z->vem >> 8);
  466. X          warn(errbuf, z->zname);
  467. X        }
  468. X        if (z->ver != 10 && z->ver != 11)
  469. X        {
  470. X          sprintf(errbuf, "needs unzip %d.%d on system type %d: ",
  471. X                  (z->ver & 0xff) / 10, (z->ver & 0xff) % 10, z->ver >> 8);
  472. X          warn(errbuf, z->zname);
  473. X        }
  474. X        if (z->flg != z->lflg)
  475. X        {
  476. X          sprintf(errbuf, "local flags = 0x%04x, central = 0x%04x: ",
  477. X                  z->lflg, z->flg);
  478. X          warn(errbuf, z->zname);
  479. X        }
  480. X        else if (z->flg & ~7)
  481. X        {
  482. X          sprintf(errbuf, "undefined bits used in flags = 0x%04x: ", z->flg);
  483. X          warn(errbuf, z->zname);
  484. X        }
  485. X        if (z->how > IMPLODE)
  486. X        {
  487. X          sprintf(errbuf, "unknown compression method %u: ", z->how);
  488. X          warn(errbuf, z->zname);
  489. X        }
  490. X        if (z->dsk)
  491. X        {
  492. X          sprintf(errbuf, "starts on disk %u: ", z->dsk);
  493. X          warn(errbuf, z->zname);
  494. X        }
  495. X        if (z->att & ~1)
  496. X        {
  497. X          sprintf(errbuf, "unknown internal attributes = 0x%04x: ", z->att);
  498. X          warn(errbuf, z->zname);
  499. X        }
  500. X        if (((n = z->vem >> 8) != 3) && n != 2 && z->atx & ~0xffL)
  501. X        {
  502. X          sprintf(errbuf, "unknown external attributes = 0x%08lx: ", z->atx);
  503. X          warn(errbuf, z->zname);
  504. X        }
  505. X        if (z->ext || z->cext)
  506. X          if (z->ext == z->cext && z->extra == z->cextra)
  507. X          {
  508. X            sprintf(errbuf, "has %d bytes of extra data: ", z->ext);
  509. X            warn(errbuf, z->zname);
  510. X          }
  511. X          else
  512. X          {
  513. X            sprintf(errbuf,
  514. X                    "local extra (%d bytes) != central extra (%d bytes): ",
  515. X                    z->ext, z->cext);
  516. X            warn(errbuf, z->zname);
  517. X          }
  518. X      }
  519. X
  520. X      /* Clear actions */
  521. X      z->mark = 0;
  522. X      z->trash = 0;
  523. X
  524. X      /* Update file offset */
  525. X      p += 4 + CENHEAD + z->nam + z->cext + z->com;
  526. X
  527. X      /* Advance to next header structure */
  528. X      z = z->nxt;
  529. X
  530. X      /* Read next signature */
  531. X      if (fread(b, 4, 1, f) != 1)
  532. X        return ferror(f) ? ZE_READ : ZE_EOF;
  533. X    }
  534. X    
  535. X    /* Read end header */
  536. X    if (z != NULL || LG(b) != ENDSIG)
  537. X    {
  538. X      warn("missing end signature--probably not a zip file (did you", "");
  539. X      warn("remember to use binary mode when you transferred it?)", "");
  540. X      return ZE_FORM;
  541. X    }
  542. X    if (fread(b, ENDHEAD, 1, f) != 1)
  543. X      return ferror(f) ? ZE_READ : ZE_EOF;
  544. X    if (SH(ENDDSK + b) || SH(ENDBEG + b) ||
  545. X        SH(ENDSUB + b) != SH(ENDTOT + b))
  546. X      warn("multiple disk information ignored", "");
  547. X    if (zcount != SH(ENDSUB + b))
  548. X    {
  549. X      warn("count in end of central directory incorrect", "");
  550. X      return ZE_FORM;
  551. X    }
  552. X    if (LG(ENDSIZ + b) != p - s)
  553. X    {
  554. X      warn("central directory size is incorrect", "");
  555. X      return ZE_FORM;
  556. X    }
  557. X    if (LG(ENDOFF + b) != s)
  558. X    {
  559. X      warn("central directory start is incorrect", "");
  560. X      return ZE_FORM;
  561. X    }
  562. X    cenbeg = s;
  563. X    zcomlen = SH(ENDCOM + b);
  564. X    if (zcomlen)
  565. X    {
  566. X      if ((zcomment = malloc(zcomlen)) == NULL)
  567. X        return ZE_MEM;
  568. X      if (fread(zcomment, zcomlen, 1, f) != 1)
  569. X      {
  570. X        free((voidp *)zcomment);
  571. X        return ferror(f) ? ZE_READ : ZE_EOF;
  572. X      }
  573. X    }
  574. X    if (zipbeg)
  575. X    {
  576. X      sprintf(errbuf, " has a preamble of %ld bytes", zipbeg);
  577. X      warn(zipfile, errbuf);
  578. X    }
  579. X    if (getc(f) != EOF)
  580. X      warn("garbage at end of zip file ignored", "");
  581. X
  582. X    /* Done with zip file for now */
  583. X    fclose(f);
  584. X    
  585. X    /* If one or more files, sort by name */
  586. X    if (zcount)
  587. X    {
  588. X      if ((x = zsort =
  589. X          (struct zlist far **)malloc(zcount * sizeof(struct zlist far *))) ==
  590. X          NULL)
  591. X        return ZE_MEM;
  592. X      for (z = zfiles; z != NULL; z = z->nxt)
  593. X        *x++ = z;
  594. X      qsort((char *)zsort, zcount, sizeof(struct zlist far *), zqcmp);
  595. X    }
  596. X  }
  597. X  return ZE_OK;
  598. X}
  599. X
  600. X
  601. Xint putlocal(z, f)
  602. Xstruct zlist far *z;    /* zip entry to write local header for */
  603. XFILE *f;                /* file to write to */
  604. X/* Write a local header described by *z to file *f.  Return an error code
  605. X   in the ZE_ class. */
  606. X{
  607. X  PUTLG(LOCSIG, f);
  608. X  PUTSH(z->ver, f);
  609. X  PUTSH(z->lflg, f);
  610. X  PUTSH(z->how, f);
  611. X  PUTLG(z->tim, f);
  612. X  PUTLG(z->crc, f);
  613. X  PUTLG(z->siz, f);
  614. X  PUTLG(z->len, f);
  615. X  PUTSH(z->nam, f);
  616. X  PUTSH(z->ext, f);
  617. X  if (fwrite(z->zname, 1, z->nam, f) != z->nam ||
  618. X      z->ext && fwrite(z->extra, 1, z->ext, f) != z->ext)
  619. X    return ZE_TEMP;
  620. X  return ZE_OK;
  621. X}
  622. X
  623. X
  624. Xint putcentral(z, f)
  625. Xstruct zlist far *z;    /* zip entry to write central header for */
  626. XFILE *f;                /* file to write to */
  627. X/* Write a central header described by *z to file *f.  Return an error code
  628. X   in the ZE_ class. */
  629. X{
  630. X  PUTLG(CENSIG, f);
  631. X  PUTSH(z->vem, f);
  632. X  PUTSH(z->ver, f);
  633. X  PUTSH(z->flg, f);
  634. X  PUTSH(z->how, f);
  635. X  PUTLG(z->tim, f);
  636. X  PUTLG(z->crc, f);
  637. X  PUTLG(z->siz, f);
  638. X  PUTLG(z->len, f);
  639. X  PUTSH(z->nam, f);
  640. X  PUTSH(z->cext, f);
  641. X  PUTSH(z->com, f);
  642. X  PUTSH(z->dsk, f);
  643. X  PUTSH(z->att, f);
  644. X  PUTLG(z->atx, f);
  645. X  PUTLG(z->off, f);
  646. X  if (fwrite(z->zname, 1, z->nam, f) != z->nam ||
  647. X      z->cext && fwrite(z->cextra, 1, z->cext, f) != z->cext ||
  648. X      z->com && fwrite(z->comment, 1, z->com, f) != z->com)
  649. X    return ZE_TEMP;
  650. X  return ZE_OK;
  651. X}
  652. X
  653. X
  654. Xint putend(n, s, c, m, z, f)
  655. Xint n;                  /* number of entries in central directory */
  656. Xulg s, c;               /* size and offset of central directory */
  657. Xextent m;               /* length of zip file comment (0 if none) */
  658. Xchar *z;                /* zip file comment if m != 0 */
  659. XFILE *f;                /* file to write to */
  660. X/* Write the end of central directory data to file *f.  Return an error code
  661. X   in the ZE_ class. */
  662. X{
  663. X  PUTLG(ENDSIG, f);
  664. X  PUTSH(0, f);
  665. X  PUTSH(0, f);
  666. X  PUTSH(n, f);
  667. X  PUTSH(n, f);
  668. X  PUTLG(s, f);
  669. X  PUTLG(c, f);
  670. X  PUTSH(m, f);
  671. X  if (m && fwrite(z, 1, m, f) != m)
  672. X    return ZE_TEMP;
  673. X  return ZE_OK;
  674. X}
  675. X
  676. X
  677. X#ifndef UTIL
  678. X
  679. Xlocal char *cutpath(p)
  680. Xchar *p;                /* path string */
  681. X/* Cut the last path component off the name *p in place.  Return p. */
  682. X{
  683. X  char *r;              /* pointer to last path delimiter */
  684. X
  685. X#ifdef VMS                      /* change [w.x.y]z to [w.x]y.DIR */
  686. X  if ((r = strrchr(p, ']')) != NULL)
  687. X  {
  688. X    *r = 0;
  689. X    if ((r = strrchr(p, '.')) != NULL)
  690. X    {
  691. X      *r = ']';
  692. X      strcat(r, ".DIR");        /* this assumes a little padding--see PAD */
  693. X    }
  694. X    else
  695. X      *p = 0;
  696. X  }
  697. X  else
  698. X    *p = 0;
  699. X#else /* !VMS */                /* change w/x/y/z to w/x/y */
  700. X  if ((r = strrchr(p, '/')) != NULL)
  701. X    *r = 0;
  702. X  else
  703. X    *p = 0;
  704. X#endif /* ?VMS */
  705. X  return p;
  706. X}
  707. X
  708. X
  709. Xint trash()
  710. X/* Delete the compressed files and the directories that contained the deleted
  711. X   files, if empty.  Return an error code in the ZE_ class.  Failure of
  712. X   destroy() or deletedir() is ignored. */
  713. X{
  714. X  extent i;             /* counter on deleted names */
  715. X  extent k;             /* number of deleted directories this pass */
  716. X  extent n;             /* number of deleted names left to handle */
  717. X  struct zlist far **s; /* table of zip entries to handle, sorted */
  718. X  struct zlist far *z;  /* current zip entry */
  719. X
  720. X  /* Count and delete marked names */
  721. X  n = 0;
  722. X  for (z = zfiles; z != NULL; z = z->nxt)
  723. X    if (z->mark || z->trash)
  724. X    {
  725. X      z->mark = 1;
  726. X      n++;
  727. X      if (verbose)
  728. X        printf("zip diagnostic: trashing file %s\n", z->name);
  729. X      destroy(z->name);
  730. X    }
  731. X
  732. X  /* Try to delete all paths that lead up to marked names */
  733. X  if (n)
  734. X  {
  735. X    if ((s = (struct zlist far **)malloc((n+1)*sizeof(struct zlist far *))) ==
  736. X        NULL ||
  737. X        (s[0] = (struct zlist far *)farmalloc(sizeof(struct zlist))) == NULL)
  738. X      return ZE_MEM;
  739. X    s[0]->name = "";
  740. X    s++;
  741. X    do {
  742. X      n = k = 0;
  743. X      for (z = zfiles; z != NULL; z = z->nxt)
  744. X        if (z->mark)
  745. X          s[n++] = z;
  746. X      qsort((char *)s, n, sizeof(struct zlist far *), zqcmp);
  747. X      for (i = 0; i < n; i++)
  748. X        if (*cutpath(s[i]->name) && strcmp(s[i]->name, s[i-1]->name))
  749. X        {
  750. X          if (verbose)
  751. X            printf("zip diagnostic: trashing directory %s\n", s[i]->name);
  752. X          deletedir(s[i]->name);
  753. X          k++;
  754. X        }
  755. X        else
  756. X          s[i]->mark = 0;
  757. X    } while (k);
  758. X    farfree((voidp far *)((--s)[0]));
  759. X    free((voidp *)s);
  760. X  }
  761. X  return ZE_OK;
  762. X}
  763. X
  764. X#endif /* !UTIL */
  765. END_OF_FILE
  766.   if test 20530 -ne `wc -c <'zipfile.c'`; then
  767.     echo shar: \"'zipfile.c'\" unpacked with wrong size!
  768.   fi
  769.   # end of 'zipfile.c'
  770. fi
  771. if test -f 'zipsplit.c' -a "${1}" != "-c" ; then 
  772.   echo shar: Will not clobber existing file \"'zipsplit.c'\"
  773. else
  774.   echo shar: Extracting \"'zipsplit.c'\" \(16863 characters\)
  775.   sed "s/^X//" >'zipsplit.c' <<'END_OF_FILE'
  776. X/*
  777. X
  778. X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
  779. X Permission is granted to any individual or institution to use, copy, or
  780. X redistribute this software so long as all of the original files are included
  781. X unmodified, that it is not sold for profit, and that this copyright notice
  782. X is retained.
  783. X
  784. X*/
  785. X
  786. X/*
  787. X *  zipsplit.c by Mark Adler.
  788. X */
  789. X
  790. X#define UTIL
  791. X#include "revision.h"
  792. X#include "zip.h"
  793. X#include <signal.h>
  794. X
  795. X#define DEFSIZ 36000L   /* Default split size (change in help() too) */
  796. X#ifdef MSDOS
  797. X#  define NL 2          /* Number of bytes written for a \n */
  798. X#else /* !MSDOS */
  799. X#  define NL 1          /* Number of bytes written for a \n */
  800. X#endif /* ?MSDOS */
  801. X#define INDEX "zipsplit.idx"    /* Name of index file */
  802. X
  803. X
  804. X/* Local functions */
  805. X#ifdef PROTO
  806. X   local void err(int, char *);
  807. X   local void handler(int);
  808. X   local void license(void);
  809. X   local void help(void);
  810. X   local extent simple(ulg *, extent, ulg, ulg);
  811. X   local int descmp(voidp *, voidp *);
  812. X   local extent greedy(ulg *, extent, ulg, ulg);
  813. X   void main(int, char **);
  814. X#endif /* PROTO */
  815. X
  816. X
  817. X/* Output zip files */
  818. Xlocal char template[16];        /* name template for output files */
  819. Xlocal int zipsmade = 0;         /* number of zip files made */
  820. Xlocal int indexmade = 0;        /* true if index file made */
  821. Xlocal char *path = NULL;        /* space for full name */
  822. Xlocal char *name;               /* where name goes in path[] */
  823. X
  824. X
  825. Xlocal void err(c, h)
  826. Xint c;                  /* error code from the ZE_ class */
  827. Xchar *h;                /* message about how it happened */
  828. X/* Issue a message for the error, clean up files and memory, and exit. */
  829. X{
  830. X  if (PERR(c))
  831. X    perror("zipsplit error");
  832. X  fprintf(stderr, "zipsplit error: %s (%s)\n", errors[c-1], h);
  833. X  if (indexmade)
  834. X  {
  835. X    strcpy(name, INDEX);
  836. X    destroy(path);
  837. X  }
  838. X  for (; zipsmade; zipsmade--)
  839. X  {
  840. X    sprintf(name, template, zipsmade);
  841. X    destroy(path);
  842. X  }
  843. X  if (path != NULL)
  844. X    free((voidp *)path);
  845. X  if (zipfile != NULL)
  846. X    free((voidp *)zipfile);
  847. X#ifdef VMS
  848. X  exit(0);
  849. X#else /* !VMS */
  850. X  exit(c);
  851. X#endif /* ?VMS */
  852. X}
  853. X
  854. X
  855. X
  856. Xlocal void handler(s)
  857. Xint s;                  /* signal number (ignored) */
  858. X/* Upon getting a user interrupt, abort cleanly using err(). */
  859. X{
  860. X#ifndef MSDOS
  861. X  putc('\n', stderr);
  862. X#endif /* !MSDOS */
  863. X  err(ZE_ABORT, "aborting");
  864. X  s++;                                  /* keep some compilers happy */
  865. X}
  866. X
  867. X
  868. Xvoid warn(a, b)
  869. Xchar *a, *b;            /* message strings juxtaposed in output */
  870. X/* Print a warning message to stderr and return. */
  871. X{
  872. X  fprintf(stderr, "zipsplit warning: %s%s\n", a, b);
  873. X}
  874. X
  875. X
  876. Xlocal void license()
  877. X/* Print license information to stdout. */
  878. X{
  879. X  extent i;             /* counter for copyright array */
  880. X
  881. X  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
  882. X    puts(copyright[i]);
  883. X  for (i = 0; i < sizeof(disclaimer)/sizeof(char *); i++)
  884. X    puts(disclaimer[i]);
  885. X}
  886. X
  887. X
  888. Xlocal void help()
  889. X/* Print help (along with license info) to stdout. */
  890. X{
  891. X  extent i;             /* counter for help array */
  892. X
  893. X  /* help array */
  894. X  static char *text[] = {
  895. X"",
  896. X"ZipSplit %d.%d (%s)",
  897. X"Usage:  zipsplit [-ti] [-n size] [-b path] zipfile",
  898. X"  -t   report how many files it will take, but don't make them",
  899. X"  -i   make index (zipsplit.idx) and count its size against first zip file",
  900. X"  -n   make zip files no larger than \"size\" (default = 36000)",
  901. X"  -b   use \"path\" for the output zip files",
  902. X"  -s   do a sequential split even if it takes more zip files",
  903. X"  -h   show this help               -l   show software license"
  904. X  };
  905. X
  906. X  for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
  907. X    puts(copyright[i]);
  908. X  for (i = 0; i < sizeof(text)/sizeof(char *); i++)
  909. X  {
  910. X    printf(text[i], REVISION / 10, REVISION % 10, REVDATE);
  911. X    putchar('\n');
  912. X  }
  913. X}
  914. X
  915. X
  916. Xlocal extent simple(a, n, c, d)
  917. Xulg *a;         /* items to put in bins, return value: destination bins */
  918. Xextent n;       /* number of items */
  919. Xulg c;          /* capacity of each bin */
  920. Xulg d;          /* amount to deduct from first bin */
  921. X/* Return the number of bins of capacity c that are needed to contain the
  922. X   integers in a[0..n-1] placed sequentially into the bins.  The value d
  923. X   is deducted initially from the first bin (space for index).  The entries
  924. X   in a[] are replaced by the destination bins. */
  925. X{
  926. X  extent k;     /* current bin number */
  927. X  ulg t;        /* space used in current bin */
  928. X
  929. X  t = k = 0;
  930. X  while (n--)
  931. X  {
  932. X    if (*a + t > c - (k == 0 ? d : 0))
  933. X    {
  934. X      k++;
  935. X      t = 0;
  936. X    }
  937. X    t += *a;
  938. X    *(ulg huge *)a++ = k;
  939. X  }
  940. X  return k + 1;
  941. X}
  942. X
  943. X
  944. Xlocal int descmp(a, b)
  945. Xvoidp *a, *b;           /* pointers to pointers to ulg's to compare */
  946. X/* Used by qsort() in greedy() to do a descending sort. */
  947. X{
  948. X  return **(ulg **)a < **(ulg **)b ? 1 : (**(ulg **)a > **(ulg **)b ? -1 : 0);
  949. X}
  950. X
  951. X
  952. Xlocal extent greedy(a, n, c, d)
  953. Xulg *a;         /* items to put in bins, return value: destination bins */
  954. Xextent n;       /* number of items */
  955. Xulg c;          /* capacity of each bin */
  956. Xulg d;          /* amount to deduct from first bin */
  957. X/* Return the number of bins of capacity c that are needed to contain the
  958. X   items with sizes a[0..n-1] placed non-sequentially into the bins.  The
  959. X   value d is deducted initially from the first bin (space for index).
  960. X   The entries in a[] are replaced by the destination bins. */
  961. X{
  962. X  ulg *b;       /* space left in each bin (malloc'ed for each m) */
  963. X  ulg *e;       /* copy of argument a[] (malloc'ed) */
  964. X  extent i;     /* steps through items */
  965. X  extent j;     /* steps through bins */
  966. X  extent k;     /* best bin to put current item in */
  967. X  extent m;     /* current number of bins */
  968. X  ulg **s;      /* pointers to e[], sorted descending (malloc'ed) */
  969. X  ulg t;        /* space left in best bin (index k) */
  970. X
  971. X  /* Algorithm:
  972. X     1. Copy a[] to e[] and sort pointers to e[0..n-1] (in s[]), in
  973. X        descending order.
  974. X     2. Compute total of s[] and set m to the smallest number of bins of
  975. X        capacity c that can hold the total.
  976. X     3. Allocate m bins.
  977. X     4. For each item in s[], starting with the largest, put it in the
  978. X        bin with the smallest current capacity greater than or equal to the
  979. X        item's size.  If no bin has enough room, increment m and go to step 4.
  980. X     5. Else, all items ended up in a bin--return m.
  981. X  */
  982. X
  983. X  /* Copy a[] to e[], put pointers to e[] in s[], and sort s[].  Also compute
  984. X     the initial number of bins (minus 1). */
  985. X  if ((e = (ulg *)malloc(n * sizeof(ulg))) == NULL ||
  986. X      (s = (ulg **)malloc(n * sizeof(ulg *))) == NULL)
  987. X  {
  988. X    if (e != NULL)
  989. X      free((voidp *)e);
  990. X    err(ZE_MEM, "was trying a smart split");
  991. X    return 0;                           /* only to make compiler happy */
  992. X  }
  993. X  memcpy((char *)e, (char *)a, n * sizeof(ulg));
  994. X  for (t = i = 0; i < n; i++)
  995. X    t += *(s[i] = e + i);
  996. X  m = (extent)((t + c - 1) / c) - 1;    /* pre-decrement for loop */
  997. X  qsort((char *)s, n, sizeof(ulg *), descmp);
  998. X
  999. X  /* Stuff bins until successful */
  1000. X  do {
  1001. X    /* Increment the number of bins, allocate and initialize bins */
  1002. X    if ((b = (ulg *)malloc(++m * sizeof(ulg))) == NULL)
  1003. X    {
  1004. X      free((voidp *)s);
  1005. X      free((voidp *)e);
  1006. X      err(ZE_MEM, "was trying a smart split");
  1007. X    }
  1008. X    b[0] = c - d;                       /* leave space in first bin */
  1009. X    for (j = 1; j < m; j++)
  1010. X      b[j] = c;
  1011. X
  1012. X    /* Fill the bins greedily */
  1013. X    for (i = 0; i < n; i++)
  1014. X    {
  1015. X      /* Find smallest bin that will hold item i (size s[i]) */
  1016. X      t = c + 1;
  1017. X      for (k = j = 0; j < m; j++)
  1018. X        if (*s[i] <= b[j] && b[j] < t)
  1019. X          t = b[k = j];
  1020. X
  1021. X      /* If no bins big enough for *s[i], try next m */
  1022. X      if (t == c + 1)
  1023. X        break;
  1024. X
  1025. X      /* Diminish that bin and save where it goes */
  1026. X      b[k] -= *s[i];
  1027. X      a[(int)((ulg huge *)(s[i]) - (ulg huge *)e)] = k;
  1028. X    }
  1029. X
  1030. X    /* Clean up */
  1031. X    free((voidp *)b);
  1032. X
  1033. X    /* Do until all items put in a bin */
  1034. X  } while (i < n);
  1035. X
  1036. X  /* Done--clean up and return the number of bins needed */
  1037. X  free((voidp *)s);
  1038. X  free((voidp *)e);
  1039. X  return m;
  1040. X}
  1041. X
  1042. X
  1043. Xvoid main(argc, argv)
  1044. Xint argc;               /* number of tokens in command line */
  1045. Xchar **argv;            /* command line tokens */
  1046. X/* Split a zip file into several zip files less than a specified size.  See
  1047. X   the command help in help() above. */
  1048. X{
  1049. X  ulg *a;               /* malloc'ed list of sizes, dest bins */
  1050. X  extent *b;            /* heads of bin linked lists (malloc'ed) */
  1051. X  ulg c;                /* bin capacity, start of central directory */
  1052. X  int d;                /* if true, just report the number of disks */
  1053. X  FILE *e;              /* input zip file */
  1054. X  FILE *f;              /* output index and zip files */
  1055. X  extent g;             /* number of bins from greedy(), entry to write */
  1056. X  int h;                /* how to split--true means simple split, counter */
  1057. X  ulg i;                /* size of index file or zero if none */
  1058. X  extent j;             /* steps through zip entries, bins */
  1059. X  int k;                /* next argument type */
  1060. X  ulg *p;               /* malloc'ed list of sizes, dest bins for greedy() */
  1061. X  char *q;              /* steps through option characters */
  1062. X  int r;                /* temporary variable, counter */
  1063. X  extent s;             /* number of bins needed */
  1064. X  ulg t;                /* total of sizes, end of central directory */
  1065. X  struct zlist far **w; /* malloc'ed table for zfiles linked list */
  1066. X  int x;                /* if true, make an index file */
  1067. X  struct zlist far *z;  /* steps through zfiles linked list */
  1068. X
  1069. X
  1070. X  /* If no args, show help */
  1071. X  if (argc == 1)
  1072. X  {
  1073. X    help();
  1074. X    exit(0);
  1075. X  }
  1076. X
  1077. X  /* Go through args */
  1078. X  signal(SIGINT, handler);
  1079. X  signal(SIGTERM, handler);
  1080. X  k = h = x = d = 0;
  1081. X  c = DEFSIZ;
  1082. X  for (r = 1; r < argc; r++)
  1083. X    if (*argv[r] == '-')
  1084. X      if (argv[r][1])
  1085. X        for (q = argv[r]+1; *q; q++)
  1086. X          switch(*q)
  1087. X          {
  1088. X            case 'b':   /* Specify path for output files */
  1089. X              if (k)
  1090. X                err(ZE_PARMS, "options are separate and precede zip file");
  1091. X              else
  1092. X                k = 1;          /* Next non-option is path */
  1093. X              break;
  1094. X            case 'h':   /* Show help */
  1095. X              help();  exit(0);
  1096. X            case 'i':   /* Make an index file */
  1097. X              x = 1;
  1098. X              break;
  1099. X            case 'l':   /* Show copyright and disclaimer */
  1100. X              license();  exit(0);
  1101. X            case 'n':   /* Specify maximum size of resulting zip files */
  1102. X              if (k)
  1103. X                err(ZE_PARMS, "options are separate and precede zip file");
  1104. X              else
  1105. X                k = 2;          /* Next non-option is size */
  1106. X              break;
  1107. X            case 's':
  1108. X              h = 1;    /* Only try simple */
  1109. X              break;
  1110. X            case 't':   /* Just report number of disks */
  1111. X              d = 1;
  1112. X              break;
  1113. X            default:
  1114. X              err(ZE_PARMS, "unknown option");
  1115. X          }
  1116. X      else
  1117. X        err(ZE_PARMS, "zip file cannot be stdin");
  1118. X    else
  1119. X      if (k == 0)
  1120. X        if (zipfile == NULL)
  1121. X        {
  1122. X          if ((zipfile = ziptyp(argv[r])) == NULL)
  1123. X            err(ZE_MEM, "was processing arguments");
  1124. X        }
  1125. X        else
  1126. X          err(ZE_PARMS, "can only specify one zip file");
  1127. X      else if (k == 1)
  1128. X      {
  1129. X        tempath = argv[r];
  1130. X        k = 0;
  1131. X      }
  1132. X      else              /* k must be 2 */
  1133. X      {
  1134. X        if ((c = (ulg)atol(argv[r])) < 100)     /* 100 is smallest zip file */
  1135. X          err(ZE_PARMS, "invalid size given");
  1136. X        k = 0;
  1137. X      }
  1138. X  if (zipfile == NULL)
  1139. X    err(ZE_PARMS, "need to specify zip file");
  1140. X
  1141. X
  1142. X  /* Read zip file */
  1143. X  if ((r = readzipfile()) != ZE_OK)
  1144. X    err(r, zipfile);
  1145. X  if (zfiles == NULL)
  1146. X    err(ZE_NAME, zipfile);
  1147. X
  1148. X  /* Make a list of sizes and check against capacity.  Also compute the
  1149. X     size of the index file. */
  1150. X  c -= ENDHEAD + 4;                     /* subtract overhead/zipfile */
  1151. X  if ((a = (ulg *)malloc(zcount * sizeof(ulg))) == NULL ||
  1152. X      (w = (struct zlist far **)malloc(zcount * sizeof(struct zlist far *))) ==
  1153. X       NULL)
  1154. X  {
  1155. X    if (a != NULL)
  1156. X      free((voidp *)a);
  1157. X    err(ZE_MEM, "was computing split");
  1158. X    return;
  1159. X  }
  1160. X  i = t = 0;
  1161. X  for (j = 0, z = zfiles; j < zcount; j++, z = z->nxt)
  1162. X  {
  1163. X    w[j] = z;
  1164. X    if (x)
  1165. X      i += z->nam + 6 + NL;
  1166. X    t += a[j] = 8 + LOCHEAD + CENHEAD +
  1167. X           2 * (ulg)z->nam + 2 * (ulg)z->ext + z->com + z->siz;
  1168. X    if (a[j] > c)
  1169. X    {
  1170. X      free((voidp *)w);  free((voidp *)a);
  1171. X      err(ZE_BIG, z->zname);
  1172. X    }
  1173. X  }
  1174. X
  1175. X  /* Decide on split to use, report number of files */
  1176. X  if (h)
  1177. X    s = simple(a, zcount, c, i);
  1178. X  else
  1179. X  {
  1180. X    if ((p = (ulg *)malloc(zcount * sizeof(ulg))) == NULL)
  1181. X    {
  1182. X      free((voidp *)w);  free((voidp *)a);
  1183. X      err(ZE_MEM, "was computing split");
  1184. X    }
  1185. X    memcpy((char *)p, (char *)a, zcount * sizeof(ulg));
  1186. X    s = simple(a, zcount, c, i);
  1187. X    g = greedy(p, zcount, c, i);
  1188. X    if (s <= g)
  1189. X      free((voidp *)p);
  1190. X    else
  1191. X    {
  1192. X      free((voidp *)a);
  1193. X      a = p;
  1194. X      s = g;
  1195. X    }
  1196. X  }
  1197. X  printf("%d zip files w%s be made (%d%% efficiency)\n",
  1198. X         s, d ? "ould" : "ill", ((200 * ((t + c - 1)/c)) / s + 1) >> 1);
  1199. X  if (d)
  1200. X  {
  1201. X    free((voidp *)w);  free((voidp *)a);
  1202. X    free((voidp *)zipfile);
  1203. X    zipfile = NULL;
  1204. X    return;
  1205. X  }
  1206. X
  1207. X  /* Set up path for output files */
  1208. X  if ((path = malloc(tempath == NULL ? 13 : strlen(tempath) + 14)) == NULL)
  1209. X    err(ZE_MEM, "was making output file names");
  1210. X  if (tempath == NULL)
  1211. X     name = path;
  1212. X  else
  1213. X  {
  1214. X    strcpy(path, tempath);
  1215. X    if (path[0] && path[strlen(path) - 1] != '/')
  1216. X      strcat(path, "/");
  1217. X    name = path + strlen(path);
  1218. X  }
  1219. X
  1220. X  /* Write the index file */
  1221. X  if (x)
  1222. X  {
  1223. X    strcpy(name, INDEX);
  1224. X    printf("creating %s\n", path);
  1225. X    indexmade = 1;
  1226. X    if ((f = fopen(path, "w")) == NULL)
  1227. X    {
  1228. X      free((voidp *)w);  free((voidp *)a);
  1229. X      err(ZE_CREAT, path);
  1230. X    }
  1231. X    for (j = 0; j < zcount; j++)
  1232. X      fprintf(f, "%5ld %s\n", a[j] + 1, w[j]->zname);
  1233. X    if ((j = ferror(f)) != 0 || fclose(f))
  1234. X    {
  1235. X      if (j)
  1236. X        fclose(f);
  1237. X      free((voidp *)w);  free((voidp *)a);
  1238. X      err(ZE_WRITE, path);
  1239. X    }
  1240. X  }
  1241. X
  1242. X  /* Make linked lists of results */
  1243. X  if ((b = (extent *)malloc(s * sizeof(extent))) == NULL)
  1244. X  {
  1245. X    free((voidp *)w);  free((voidp *)a);
  1246. X    err(ZE_MEM, "was computing split");
  1247. X  }
  1248. X  for (j = 0; j < s; j++)
  1249. X    b[j] = -1;
  1250. X  j = zcount;
  1251. X  while (j--)
  1252. X  {
  1253. X    g = (extent)a[j];
  1254. X    a[j] = b[g];
  1255. X    b[g] = j;
  1256. X  }
  1257. X
  1258. X  /* Make a name template for the zip files that is eight or less characters
  1259. X     before the .zip, and that will not overwrite the original zip file. */
  1260. X  for (k = 1, j = s; j >= 10; j /= 10)
  1261. X    k++;
  1262. X  if (k > 7)
  1263. X  {
  1264. X    free((voidp *)b);  free((voidp *)w);  free((voidp *)a);
  1265. X    err(ZE_PARMS, "way too many zip files must be made");
  1266. X  }
  1267. X  if ((q = strrchr(zipfile, '/')) != NULL)
  1268. X    q++;
  1269. X  else
  1270. X    q = zipfile;
  1271. X  r = 0;
  1272. X  while ((g = *q++) != 0 && g != '.' && r < 8 - k)
  1273. X    template[r++] = (char)g;
  1274. X  if (r == 0)
  1275. X    template[r++] = '_';
  1276. X  else if (g >= '0' && g <= '9')
  1277. X    template[r - 1] = (char)(template[r - 1] == '_' ? '-' : '_');
  1278. X  sprintf(template + r, "%%0%dd.zip", k);
  1279. X
  1280. X  /* Make the zip files from the linked lists of entry numbers */
  1281. X  if ((e = fopen(zipfile, FOPR)) == NULL)
  1282. X  {
  1283. X    free((voidp *)b);  free((voidp *)w);  free((voidp *)a);
  1284. X    err(ZE_NAME, zipfile);
  1285. X  }
  1286. X  free((voidp *)zipfile);
  1287. X  zipfile = NULL;
  1288. X  for (j = 0; j < s; j++)
  1289. X  {
  1290. X    sprintf(name, template, j + 1);
  1291. X    printf("creating %s\n", path);
  1292. X    zipsmade = j + 1;
  1293. X    if ((f = fopen(path, FOPW)) == NULL)
  1294. X    {
  1295. X      free((voidp *)b);  free((voidp *)w);  free((voidp *)a);
  1296. X      err(ZE_CREAT, path);
  1297. X    }
  1298. X    for (g = b[j]; g != (extent)-1; g = (extent)a[g])
  1299. X    {
  1300. X      if (fseek(e, w[g]->off, SEEK_SET))
  1301. X      {
  1302. X        free((voidp *)b);  free((voidp *)w);  free((voidp *)a);
  1303. X        err(ferror(e) ? ZE_READ : ZE_EOF, zipfile);
  1304. X      }
  1305. X      if ((r = zipcopy(w[g], e, f)) != ZE_OK)
  1306. X      {
  1307. X        free((voidp *)b);  free((voidp *)w);  free((voidp *)a);
  1308. X        if (r == ZE_TEMP)
  1309. X          err(ZE_WRITE, path);
  1310. X        else
  1311. X          err(r, zipfile);
  1312. X      }
  1313. X    }
  1314. X    if ((c = ftell(f)) == -1L)
  1315. X    {
  1316. X      free((voidp *)b);  free((voidp *)w);  free((voidp *)a);
  1317. X      err(ZE_WRITE, path);
  1318. X    }
  1319. X    for (g = b[j], k = 0; g != (extent)-1; g = (extent)a[g], k++)
  1320. X      if ((r = putcentral(w[g], f)) != ZE_OK)
  1321. X      {
  1322. X        free((voidp *)b);  free((voidp *)w);  free((voidp *)a);
  1323. X        err(ZE_WRITE, path);
  1324. X      }
  1325. X    if ((t = ftell(f)) == -1L)
  1326. X    {
  1327. X      free((voidp *)b);  free((voidp *)w);  free((voidp *)a);
  1328. X      err(ZE_WRITE, path);
  1329. X    }
  1330. X    if ((r = putend(k, t - c, c, (extent)0, (char *)NULL, f)) != ZE_OK)
  1331. X    {
  1332. X      free((voidp *)b);  free((voidp *)w);  free((voidp *)a);
  1333. X      err(ZE_WRITE, path);
  1334. X    }
  1335. X    if (ferror(f) || fclose(f))
  1336. X    {
  1337. X      free((voidp *)b);  free((voidp *)w);  free((voidp *)a);
  1338. X      err(ZE_WRITE, path);
  1339. X    }
  1340. X  }
  1341. X  free((voidp *)b);  free((voidp *)w);  free((voidp *)a);
  1342. X  fclose(e);
  1343. X
  1344. X  /* Done! */
  1345. X  exit(0);
  1346. X}
  1347. END_OF_FILE
  1348.   if test 16863 -ne `wc -c <'zipsplit.c'`; then
  1349.     echo shar: \"'zipsplit.c'\" unpacked with wrong size!
  1350.   fi
  1351.   # end of 'zipsplit.c'
  1352. fi
  1353. if test -f 'zipup.c' -a "${1}" != "-c" ; then 
  1354.   echo shar: Will not clobber existing file \"'zipup.c'\"
  1355. else
  1356.   echo shar: Extracting \"'zipup.c'\" \(10409 characters\)
  1357.   sed "s/^X//" >'zipup.c' <<'END_OF_FILE'
  1358. X/*
  1359. X
  1360. X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
  1361. X Permission is granted to any individual or institution to use, copy, or
  1362. X redistribute this software so long as all of the original files are included
  1363. X unmodified, that it is not sold for profit, and that this copyright notice
  1364. X is retained.
  1365. X
  1366. X*/
  1367. X
  1368. X/*
  1369. X *  zipup.c by Mark Adler.
  1370. X */
  1371. X
  1372. X#define NOCPYRT         /* this is not a main module */
  1373. X#include "zip.h"
  1374. X#include "revision.h"
  1375. X
  1376. X/* Use the raw functions for MSDOS and Unix to save on buffer space.
  1377. X   They're not used for VMS since it doesn't work (raw is weird on VMS).
  1378. X   (This sort of stuff belongs in fileio.c, but oh well.) */
  1379. X#ifdef VMS
  1380. X   typedef FILE *ftype;
  1381. X#  define fhow FOPR
  1382. X#  define fbad NULL
  1383. X#  define zopen(n,p) fopen(n,p)
  1384. X#  define zread(f,b,n) fread(b,1,n,f)
  1385. X#  define zclose(f) fclose(f)
  1386. X#  define zerr(f) ferror(f)
  1387. X#  define zrew(f) rewind(f)
  1388. X#else /* !VMS */
  1389. X#  ifdef MSDOS
  1390. X#    include <io.h>
  1391. X#    include <fcntl.h>
  1392. X#    define fhow (O_RDONLY|O_BINARY)
  1393. X#  else /* !MSDOS */
  1394. X     int open OF((char *, int));
  1395. X     int read OF((int, char *, int));
  1396. X     int close OF((int));
  1397. X     int lseek OF((int,long,int));
  1398. X#    define fhow 0
  1399. X#  endif /* ?MSDOS */
  1400. X   typedef int ftype;
  1401. X#  define fbad (-1)
  1402. X#  define zopen(n,p) open(n,p)
  1403. X#  define zread(f,b,n) read(f,b,n)
  1404. X#  define zclose(f) close(f)
  1405. X#  define zerr(f) (k<0)
  1406. X#  define zrew(f) lseek(f,0L,0)
  1407. X#endif /* ?VMS */
  1408. X
  1409. X
  1410. X/* Local functions */
  1411. X#ifdef PROTO
  1412. X#  ifndef UTIL
  1413. X     local int suffixes(char *, char *);
  1414. X#  endif /* !UTIL */
  1415. X#endif /* PROTO */
  1416. X
  1417. X
  1418. X/* Note: a zip "entry" includes a local header (which includes the file
  1419. X   name), an encryption header if encrypting, and the compressed data. */
  1420. X
  1421. X
  1422. Xint zipcopy(z, x, y)
  1423. Xstruct zlist far *z;    /* zip entry to copy */
  1424. XFILE *x, *y;            /* source and destination files */
  1425. X/* Copy the zip entry described by *z from file *x to file *y.  Return an
  1426. X   error code in the ZE_ class.  */
  1427. X{
  1428. X  ulg n;                /* holds local header offset */
  1429. X
  1430. X  if (fseek(x, z->off, SEEK_SET))
  1431. X    return ferror(x) ? ZE_READ : ZE_EOF;
  1432. X  if ((n = ftell(y)) == -1L)
  1433. X    return ZE_TEMP;
  1434. X  z->off = n;
  1435. X  n = 4 + LOCHEAD + (long)z->nam + (long)z->ext + z->siz;
  1436. X  return fcopy(x, y, n);
  1437. X}
  1438. X
  1439. X
  1440. X#ifndef UTIL
  1441. X
  1442. Xint percent(n, m)
  1443. Xulg n, m;               /* n is the original size, m is the new size */
  1444. X/* Return the percentage compression from n to m using only integer
  1445. X   operations */
  1446. X{
  1447. X  if (n > 0xffffffL)            /* If n >= 16M */
  1448. X  {                             /*  then divide n and m by 256 */
  1449. X    n += 0x80;  n >>= 8;
  1450. X    m += 0x80;  m >>= 8;
  1451. X  }
  1452. X  return n ? (int)(1 + (200 * (n - m))/n) >> 1 : 0;
  1453. X}
  1454. X
  1455. X
  1456. Xlocal int suffixes(a, s)
  1457. Xchar *a;                /* name to check suffix of */
  1458. Xchar *s;                /* list of suffixes separated by : or ; */
  1459. X/* Return true if a ends in any of the suffixes in the list s. */
  1460. X{
  1461. X  int m;                /* true if suffix matches so far */
  1462. X  char *p;              /* pointer into special */
  1463. X  char *q;              /* pointer into name a */
  1464. X
  1465. X  m = 1;
  1466. X  q = a + strlen(a) - 1;
  1467. X  for (p = s + strlen(s) - 1; p >= s; p--)
  1468. X    if (*p == ':' || *p == ';')
  1469. X      if (m)
  1470. X        return 1;
  1471. X      else
  1472. X      {
  1473. X        m = 1;
  1474. X        q = a + strlen(a) - 1;
  1475. X      }
  1476. X    else
  1477. X#ifdef OS2
  1478. X    {
  1479. X      m = m && q >= a && tolower(*p) == tolower(*q);
  1480. X      q--;
  1481. X    }
  1482. X#else /* !OS2 */
  1483. X      m = m && q >= a && *p == *q--;
  1484. X#endif /* ?OS2 */
  1485. X  return m;
  1486. X}
  1487. X
  1488. X
  1489. Xint zipup(z, y)
  1490. Xstruct zlist far *z;    /* zip entry to compress */
  1491. XFILE *y;                /* output file */
  1492. X/* Compress the file z->name into the zip entry described by *z and write
  1493. X   it to the file *y.  Determine the best method (store, shrink, or implode)
  1494. X   and use it.  Encrypt if requested.  Return an error code in the
  1495. X   ZE_ class. */
  1496. X{
  1497. X  ulg a;                /* attributes returned by filetime() */
  1498. X  char *b;              /* malloc'ed file buffer */
  1499. X  ulg c;                /* crc on uncompressed file data */
  1500. X  ftype f;              /* file to compress */
  1501. X  uch g;                /* flags returned by implode */
  1502. X  int h;                /* compression method chosen (how) */
  1503. X#ifndef NOIMPLODE
  1504. X  ulg i;                /* size of imploded data */
  1505. X#endif /* !NOIMPLODE */
  1506. X  extent k;             /* result of zread */
  1507. X  int l;                /* true if this file is a symbolic link */
  1508. X  int m;                /* method for this entry */
  1509. X  ulg n;                /* size of uncompressed file */
  1510. X  long q;               /* size returned by filetime */
  1511. X  int r;                /* temporary variable */
  1512. X  ulg s;                /* size of shrunk or compressed data */
  1513. X
  1514. X  /* Open file to zip up */
  1515. X  if ((z->tim = filetime(z->name, &a, &q)) == 0 || q < 0)
  1516. X    return ZE_OPEN;
  1517. X  l = issymlnk(a);
  1518. X  if (l)
  1519. X    f = fbad;
  1520. X  else if ((f = zopen(z->name, fhow)) == fbad)
  1521. X    return ZE_OPEN;
  1522. X
  1523. X  /* Select method based on the suffix and the global method */
  1524. X  m = special != NULL && suffixes(z->name, special) ? STORE : method;
  1525. X
  1526. X  /* Don't bother with shrink for "large" files (320 is what PKZIP uses--the
  1527. X     number used here must be <= BSZ) */
  1528. X  if (m == BEST && q > 512)
  1529. X    m = IMPLODE;
  1530. X  if (q == 0)
  1531. X    m = STORE;
  1532. X
  1533. X  /* Make first pass on the file, computing the crc and length, and running
  1534. X     shrink and implode on it. */
  1535. X  n = 0;
  1536. X  c = updcrc((char *)NULL, 0);
  1537. X  if ((b = malloc(BSZ)) == NULL)
  1538. X    return ZE_MEM;
  1539. X  if (m == BEST || m == SHRINK)
  1540. X    if ((r = shr_setup()) != ZE_OK)
  1541. X      return r;
  1542. X    else
  1543. X      shract = 1;
  1544. X  while ((k = l ? rdsymlnk(z->name, b, BSZ) : zread(f, b, BSZ)) > 0)
  1545. X  {
  1546. X    n += k;
  1547. X    c = updcrc(b, k);
  1548. X#ifdef MINIX
  1549. X    if (l)
  1550. X      q = k;
  1551. X#endif /* MINIX */
  1552. X    if ((m == BEST || m == SHRINK) && (r = shr_p1((uch *)b, k)) != ZE_OK)
  1553. X    {
  1554. X      free((voidp *)b);
  1555. X      shr_clear();
  1556. X      shract = 0;
  1557. X      return r;
  1558. X    }
  1559. X    if (m == BEST)              /* free up shrink data structures */
  1560. X    {
  1561. X      if ((!l && zread(f, b, BSZ) != 0)
  1562. X#ifndef VMS
  1563. X          || n != (ulg)q
  1564. X#endif /* !VMS */
  1565. X         )
  1566. X        return ZE_READ;
  1567. X      if ((r = shr_size(&s)) != ZE_OK)
  1568. X      {
  1569. X        shr_clear();
  1570. X        shract = 0;
  1571. X        return r;
  1572. X      }
  1573. X    }
  1574. X#ifndef NOIMPLODE
  1575. X    if (m == BEST || m == IMPLODE)
  1576. X    {
  1577. X      if (!impact)
  1578. X        if ((r = imp_setup(q, level)) != ZE_OK)
  1579. X          return r;
  1580. X        else
  1581. X          impact = 1;
  1582. X      if ((r = imp_p1(b, k)) != ZE_OK)
  1583. X      {
  1584. X        free((voidp *)b);
  1585. X        imp_clear();
  1586. X        impact = 0;
  1587. X        return r;
  1588. X      }
  1589. X    }
  1590. X#endif /* !NOIMPLODE */
  1591. X    if (m == BEST || l)
  1592. X      break;
  1593. X  }
  1594. X  free((voidp *)b);
  1595. X  if (!l && zerr(f))
  1596. X    return ZE_READ;
  1597. X
  1598. X  /* Determine the best method to use */
  1599. X  g = 0;
  1600. X  if (noisy && verbose)
  1601. X    printf(" (n=%lu)", n);
  1602. X  if (m == SHRINK && (r = shr_size(&s)) != ZE_OK)
  1603. X  {
  1604. X    shr_clear();
  1605. X    shract = 0;
  1606. X    return r;
  1607. X  }
  1608. X  if (noisy && verbose && (m == BEST || m == SHRINK))
  1609. X    printf(" (s=%lu)", s);
  1610. X#ifndef NOIMPLODE
  1611. X  if ((m == BEST || m == IMPLODE) && (r = imp_size(&i, &g)) != ZE_OK)
  1612. X  {
  1613. X    imp_clear();
  1614. X    impact = 0;
  1615. X    return r;
  1616. X  }
  1617. X  if (noisy && verbose && (m == BEST || m == IMPLODE))
  1618. X    printf(" (i=%lu)", i);
  1619. X  if ((m == BEST || m == IMPLODE) && i < n && (m == IMPLODE || i < s))
  1620. X  {
  1621. X    if (noisy)
  1622. X    {
  1623. X      printf(" (imploded %d%%)", percent(n, i));
  1624. X      fflush(stdout);
  1625. X    }
  1626. X    h = IMPLODE;
  1627. X    s = i;
  1628. X    if (m == BEST)
  1629. X    {
  1630. X      shr_clear();
  1631. X      shract = 0;
  1632. X    }
  1633. X    if (!l)
  1634. X      zclose(f);
  1635. X  }
  1636. X  else
  1637. X#endif /* !NOIMPLODE */
  1638. X  if ((m == BEST || m == SHRINK) && s < n)
  1639. X  {
  1640. X    if (noisy)
  1641. X    {
  1642. X      printf(" (shrunk %d%%)", percent(n, s));
  1643. X      fflush(stdout);
  1644. X    }
  1645. X    h = SHRINK;
  1646. X#ifndef NOIMPLODE
  1647. X    if (m == BEST)
  1648. X    {
  1649. X      imp_clear();
  1650. X      impact = 0;
  1651. X    }
  1652. X#endif /* !NOIMPLODE */
  1653. X    if (!l)
  1654. X      zclose(f);
  1655. X  }
  1656. X  else
  1657. X  {
  1658. X    if (noisy)
  1659. X    {
  1660. X      printf(" (stored 0%%)");
  1661. X      fflush(stdout);
  1662. X    }
  1663. X    h = STORE;
  1664. X    s = n;
  1665. X#ifndef NOIMPLODE
  1666. X    if (m == BEST || m == IMPLODE)
  1667. X    {
  1668. X      imp_clear();
  1669. X      impact = 0;
  1670. X    }
  1671. X#endif /* !NOIMPLODE */
  1672. X    if (m == BEST || m == SHRINK)
  1673. X    {
  1674. X      shr_clear();
  1675. X      shract = 0;
  1676. X    }
  1677. X  }
  1678. X
  1679. X#ifndef VMS
  1680. X  /* Check size (but not in VMS--variable record lengths mess it up) */
  1681. X  if (n != (ulg)q)
  1682. X    return ZE_READ;
  1683. X#endif /* !VMS */
  1684. X
  1685. X  /* Fill in header information and write local header to zip file */
  1686. X#ifdef OS2
  1687. X  if ( dosify < 2 )
  1688. X    dosify = IsFileSystemFAT(z->name);
  1689. X#endif /* OS2 */
  1690. X
  1691. X  /* (Assume ext, cext, com, and zname already filled in.) */
  1692. X  z->vem = dosify ? 11 :                /* Made under MSDOS by PKZIP 1.1 */
  1693. X#ifdef VMS
  1694. X                    0x200 + REVISION;   /* Made under VMS by this Zip */
  1695. X#else /* !VMS */
  1696. X#ifdef OS2
  1697. X                    0x600 + REVISION;   /* Made under OS/2 by this Zip */
  1698. X#else /* !OS2 */
  1699. X                    0x300 + REVISION;   /* Made under Unix by this Zip */
  1700. X#endif /* ?OS2 */
  1701. X#endif /* ?VMS */
  1702. X  z->ver = 10;                          /* Need PKUNZIP 1.0 */
  1703. X  z->flg = (ush)g;
  1704. X  if (key != NULL)
  1705. X    z->flg |= 1;
  1706. X  z->lflg = z->flg;
  1707. X  z->how = h;
  1708. X  z->crc = c;
  1709. X  z->siz = s;
  1710. X  if (key != NULL)
  1711. X    z->siz += 12;
  1712. X  z->len = n;
  1713. X  z->nam = strlen(z->zname);
  1714. X  z->dsk = 0;
  1715. X  z->att = 0;                           /* Assume they're all binary */
  1716. X  z->atx = dosify ? a & 0xff : a;       /* Attributes from filetime() */
  1717. X  if ((z->off = ftell(y)) == -1L)
  1718. X    return ZE_WRITE;
  1719. X  if ((r = putlocal(z, y)) != ZE_OK)
  1720. X    return r;
  1721. X
  1722. X  /* Write stored, shrunk, or imploded file to zip file */
  1723. X#ifndef EXPORT
  1724. X  if (key != NULL)
  1725. X    crypthead(key, z->crc, y);
  1726. X#endif /* !EXPORT */
  1727. X  n = ftell(y);                         /* Save offset for logic check */
  1728. X#ifndef NOIMPLODE
  1729. X  if (h == IMPLODE)
  1730. X  {
  1731. X    if ((r = imp_p2(y)) != ZE_OK)
  1732. X      return r;
  1733. X    imp_clear();
  1734. X    impact = 0;
  1735. X  }
  1736. X  else
  1737. X#endif /* !NOIMPLODE */
  1738. X  if (h == SHRINK)
  1739. X  {
  1740. X    if ((r = shr_p2(y)) != ZE_OK)
  1741. X      return r;
  1742. X    shr_clear();
  1743. X    shract = 0;
  1744. X  }
  1745. X  else
  1746. X  {
  1747. X    if (!l)
  1748. X      zrew(f);
  1749. X    if ((b = malloc(BSZ)) == NULL)
  1750. X      return ZE_MEM;
  1751. X    while ((k = l ? rdsymlnk(z->name, b, BSZ) : zread(f, b, BSZ)) > 0)
  1752. X    {
  1753. X      if (zfwrite(b, 1, k, y) != k)
  1754. X      {
  1755. X        free((voidp *)b);
  1756. X        return ZE_TEMP;
  1757. X      }
  1758. X      if (l)
  1759. X        break;
  1760. X    }
  1761. X    free((voidp *)b);
  1762. X    if (!l && zerr(f))
  1763. X      return ZE_READ;
  1764. X    if (!l)
  1765. X      zclose(f);
  1766. X  }
  1767. X
  1768. X  /* Check length of compressed data */
  1769. X  if (ftell(y) != n + s)
  1770. X    return ZE_LOGIC;
  1771. X
  1772. X  /* Done--clean up and leave */
  1773. X  if (noisy)
  1774. X  {
  1775. X    putchar('\n');
  1776. X    fflush(stdout);
  1777. X  }
  1778. X  return ZE_OK;
  1779. X}
  1780. X
  1781. X#endif /* !UTIL */
  1782. END_OF_FILE
  1783.   if test 10409 -ne `wc -c <'zipup.c'`; then
  1784.     echo shar: \"'zipup.c'\" unpacked with wrong size!
  1785.   fi
  1786.   # end of 'zipup.c'
  1787. fi
  1788. echo shar: End of archive 7 \(of 9\).
  1789. cp /dev/null ark7isdone
  1790. MISSING=""
  1791. for I in 1 2 3 4 5 6 7 8 9 ; do
  1792.     if test ! -f ark${I}isdone ; then
  1793.     MISSING="${MISSING} ${I}"
  1794.     fi
  1795. done
  1796. if test "${MISSING}" = "" ; then
  1797.     echo You have unpacked all 9 archives.
  1798.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1799. else
  1800.     echo You still must unpack the following archives:
  1801.     echo "        " ${MISSING}
  1802. fi
  1803. exit 0
  1804. exit 0 # Just in case...
  1805. -- 
  1806. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1807. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1808. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1809. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1810.